using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using UnityEngine.EventSystems;
using Newtonsoft.Json;
using DG.Tweening;

public class GamePlay : MonoBehaviour
{
    public enum EGameOperation
    {
        eDig = 0,
        eFlag = 1,
        eTip = 2,
    }

    public GridLayoutGroup m_GLGMineArea;
    public GameObject m_ItemTemplate;
    public Image ImgMainArea;
    public float BreathAnimDuration = 2f;
    public WinPanel m_WinPanel;
    public ResetConfirmPanel m_ResetConfirmPanel;
    public GameMainPanel m_GameMainPanel;
    public ScrollRect m_SRMineArea;
    public ArchiveMgr m_ArchiveManager;
    public FxManager m_FxManager;

    public void LeaveGame()
    {
        if (m_CurStatus == EGameStatus.Start) // 正常状态离开游戏，需要保存记录
        {
            int[] statusArr = GetItemLstStatus();
            ArchiveMgr.Instance.SaveArchive(
                GameMode.Instance.CurMode,
                m_MineMap,
                statusArr,
                m_GameMainPanel.PassTime,
                m_GameMainPanel.LeftMineCount,
                m_GameMainPanel.LeftPullBackCount);
        }
        else // 否则清除记录
        {
            ArchiveMgr.Instance.ClearArchive(GameMode.Instance.CurMode);
        }
        SceneManager.LoadSceneAsync("SelectMode", LoadSceneMode.Single); // 去选模式场景
    }

    public void PullBack()
    {
        ArchiveMgr.Archive archive = ArchiveMgr.Instance.LoadArchive(GameMode.Instance.CurMode);
        if (archive == null)
        {
            Debug.LogFormat("没有存档，是不是出错了");
            return;
        }

        m_CurStatus = EGameStatus.Start; // 重置游戏状态
        for (int i = 0; i < m_ItemLst.Count; i++) // 按照存档重置雷区状态
        {
            Vector2 coord = ConvertIdx2Coord(i);
            int value = m_MineMap.GetItemValue(coord);
            m_ItemLst[i].UpdateStatus((EItemStatus)archive.StatusArr[i], value);
        }


        m_GameMainPanel.StartPassTimer(archive);// 按照存档重置计时器
        m_GameMainPanel.UpdateLeftMineCount(archive.LeftMineCount); // 按照存档重置剩余雷数
        m_GameMainPanel.UpdatePullBack(m_GameMainPanel.LeftPullBackCount - 1); // 扣除一个复活机会
    }

    public void NewGame()
    {
        if (m_CurStatus == EGameStatus.Start) // 游戏进行中开新的雷图需要二次确认
        {
            m_ResetConfirmPanel.Show(_NewGame);
        }
        else
        {
            _NewGame();
        }
    }

    public void ChangeOperation(EGameOperation gameOperation)
    {
        m_CurOperation = gameOperation;
        HideBreathAnim();
        if (gameOperation == EGameOperation.eDig)
        {
        }
        else if (gameOperation == EGameOperation.eFlag)
        {
            ShowBreathAnim(FlagBreathFrom, FlagBreathTo, BreathAnimDuration);
        }
        else
        {
            ShowBreathAnim(TipBreathFrom, TipBreathTo, BreathAnimDuration);
        }
    }

    public bool CheckIsLose()
    {
        return m_CurStatus == EGameStatus.Lose;
    }

    public void SwitchQuickMark(bool open)
    {
        m_QuickMarkFlag = open;
    }


    //=========================================公私分界线==================================================

    private List<BtnItem> m_ItemLst = new List<BtnItem>();
    private MineMap m_MineMap;
    private EGameStatus m_CurStatus;
    private EGameOperation m_CurOperation;
    private int m_CurRows;
    private int m_CurLines;
    private bool m_QuickMarkFlag = true;
    private Tweener m_TweenBgColor;
    private Color FlagBreathFrom = new Color32(255, 191, 29, 255);
    private Color FlagBreathTo = new Color32(255, 125, 33, 255);
    private Color TipBreathFrom = new Color32(63, 161, 198, 255);
    private Color TipBreathTo = new Color32(16, 123, 174, 255);
    private Color DigNormal = new Color32(255, 255, 255, 100);

    void Awake()
    {
        if (ArchiveMgr.Instance == null)
        {
            GameObject.Instantiate<GameObject>(m_ArchiveManager.gameObject);
        }
        if (FxManager.Instance == null)
        {
            GameObject.Instantiate(m_FxManager.gameObject);
        }
    }


    void Start()
    {
        if (GameMode.Instance == null) return;

        m_CurStatus = EGameStatus.Start;

        ArchiveMgr.Archive archive = null;
        if (ArchiveMgr.Instance != null)
            archive = ArchiveMgr.Instance.LoadArchive(GameMode.Instance.CurMode);
        if (archive != null)
        {
            InitByArchive(archive);
        }
        else
        {
            InitByDefault();
        }
    }

    void InitMineAreaNode(int xLen, int yLen)
    {
        Transform mineArea = m_GLGMineArea.transform;
        for (int i = 0; i < xLen; i++)
        {
            int tempI = i;
            for (int j = 0; j < yLen; j++)
            {
                int tempJ = j;
                GameObject go = GameObject.Instantiate(m_ItemTemplate, mineArea);
                go.name = string.Format("Item_{0}_{1}", i, j);
                BtnItem item = go.GetComponent<BtnItem>();
                m_ItemLst.Add(item);

                item.m_ClickCallback = (code) =>
                {
                    OnBtnItemClick(tempI, tempJ, (PointerEventData.InputButton)code);
                };
            }
        }
    }

    void InitByArchive(ArchiveMgr.Archive archive)
    {
        m_MineMap = archive.Map;
        m_CurRows = m_MineMap.VerticalCount;
        m_CurLines = m_MineMap.HorizontalCount;
        InitMineAreaNode(m_MineMap.HorizontalCount, m_MineMap.VerticalCount);

        int[] statusArr = archive.StatusArr;
        for (int i = 0; i < m_ItemLst.Count; i++)
        {
            BtnItem item = m_ItemLst[i];
            Vector2 coord = ConvertIdx2Coord(i);
            int value = m_MineMap.GetItemValue(coord);
            item.UpdateStatus((EItemStatus)statusArr[i], value);
        }

        UpdateMineAreaSize(m_MineMap.VerticalCount, m_MineMap.HorizontalCount);

        m_GameMainPanel.StartPassTimer(archive); // 重新显示计时器
        m_GameMainPanel.UpdateLeftMineCount(archive.LeftMineCount); // 重置剩余雷数
        m_GameMainPanel.UpdatePullBack(archive.LeftPullBackCount); // 重置退一步次数
        m_GameMainPanel.SelectOperation(EGameOperation.eDig);// 重置雷区操作类型
    }

    void InitByDefault()
    {
        m_MineMap = GetNewMap();
        InitMineAreaNode(m_MineMap.HorizontalCount, m_MineMap.VerticalCount);
        UpdateMineAreaSize(m_CurRows, m_CurLines);

        m_GameMainPanel.StartPassTimer(null); // 重新显示计时器
        m_GameMainPanel.UpdateLeftMineCount(GameMode.Instance.MineCount); // 重置剩余雷数
        m_GameMainPanel.UpdatePullBack(GameMode.Instance.GetCurPullBackCount()); // 重置退一步次数
        m_GameMainPanel.SelectOperation(EGameOperation.eDig);// 重置雷区操作类型

        OpenFirstEmptyItem();
    }

    MineMap GetNewMap()
    {
        CalcRowAndLine();
        return new MineMap(m_CurLines, m_CurRows, GameMode.Instance.MineCount);
    }

    void CalcRowAndLine()
    {
        Transform mineArea = m_GLGMineArea.transform;
        RectTransform parentRect = mineArea.parent.GetComponent<RectTransform>();
        float height = parentRect.rect.height;
        float pt = m_GLGMineArea.padding.top;
        float pb = m_GLGMineArea.padding.bottom;
        float sy = m_GLGMineArea.spacing.y;
        float cy = m_GLGMineArea.cellSize.y;
        m_CurRows = Mathf.FloorToInt((height - pt - pb + sy) / (cy + sy));
        m_CurRows = Mathf.Min(m_CurRows, GameMode.Instance.YLen);
        m_CurLines = Mathf.CeilToInt(GameMode.Instance.XLen * GameMode.Instance.YLen / m_CurRows);
    }

    void UpdateMineAreaSize(int rows, int lines)
    {
        m_GLGMineArea.constraint = GridLayoutGroup.Constraint.FixedRowCount;
        m_GLGMineArea.constraintCount = rows;

        Transform mineArea = m_GLGMineArea.transform;
        RectTransform mineRect = mineArea.GetComponent<RectTransform>();
        mineRect.sizeDelta = new Vector2(
                m_GLGMineArea.cellSize.x * lines + m_GLGMineArea.spacing.x * (lines - 1),
                m_GLGMineArea.cellSize.y * rows + m_GLGMineArea.spacing.y * (rows - 1)
            ) + new Vector2(
                m_GLGMineArea.padding.left + m_GLGMineArea.padding.right,
                m_GLGMineArea.padding.top + m_GLGMineArea.padding.bottom
            );

        RectTransform srMineAreaRect = m_SRMineArea.GetComponent<RectTransform>();
        m_SRMineArea.horizontal = mineRect.sizeDelta.x >= srMineAreaRect.rect.width;
        m_SRMineArea.vertical = mineRect.sizeDelta.y >= srMineAreaRect.rect.height;
    }

    void OnBtnItemClick(int x, int y, PointerEventData.InputButton code)
    {
        AudioManager.PlayClickItemAudio();

        if (m_CurStatus != EGameStatus.Start) return;

        int idx = ConvertCoord2Idx(x, y);
        if (m_ItemLst[idx].IsMark())
        {
            OnItemMarkClick(idx, code);
        }
        else if (m_ItemLst[idx].IsTip())
        {
            OnItemTipClick(x, y, code);
        }
        else if (m_ItemLst[idx].IsEmpty())
        {
            OnItemEmptyClick(idx);
        }
        else if (m_ItemLst[idx].IsMineCount())
        {
            OnItemMineCountClick(x, y);
        }
        else if (m_ItemLst[idx].IsOpen() == false)
        {
            OnItemCloseClick(x, y, code);
        }
    }

    // 点击被标记旗子的格子的处理方式
    void OnItemMarkClick(int idx, PointerEventData.InputButton code)
    {
        if (code == PointerEventData.InputButton.Right || m_CurOperation == EGameOperation.eFlag)
        {
            m_ItemLst[idx].MarkFlag(false);
            m_GameMainPanel.ModifyLeftMineCount(true);
        }
    }

    // 点击被标记问号的格子的处理方式
    void OnItemTipClick(int x, int y, PointerEventData.InputButton code)
    {
        if (code == PointerEventData.InputButton.Middle || m_CurOperation == EGameOperation.eTip)
        {
            int idx = ConvertCoord2Idx(x, y);
            m_ItemLst[idx].MarkTip(false);
        }
        else if (code == PointerEventData.InputButton.Right || m_CurOperation == EGameOperation.eFlag)
        {
            int idx = ConvertCoord2Idx(x, y);
            m_ItemLst[idx].MarkFlag(true);
            m_GameMainPanel.ModifyLeftMineCount(false);
        }
        else if (code == PointerEventData.InputButton.Left)
        {
            OpenItem(x, y);
        }
    }

    // 空白格暂不处理
    void OnItemEmptyClick(int idx)
    {
        return;
    }

    // 点击数字的处理，需要根据已标记和关闭格的数量来辅助标记或者辅助打开格子
    void OnItemMineCountClick(int x, int y)
    {
        if (m_QuickMarkFlag == false) return;

        int markCount = 0;
        List<BtnItem> closeItemLst = new List<BtnItem>();
        List<Vector2> closeItemCoordLst = new List<Vector2>();

        if (x >= 1 && y >= 1)
        {
            int idx = ConvertCoord2Idx(x - 1, y - 1);
            if (m_ItemLst[idx].IsMark()) markCount++;
            else if (m_ItemLst[idx].IsOpen() == false)
            {
                closeItemLst.Add(m_ItemLst[idx]);
                closeItemCoordLst.Add(new Vector2(x - 1, y - 1));
            }
        }//  左下角
        if (y >= 1)
        {
            int idx = ConvertCoord2Idx(x, y - 1);
            if (m_ItemLst[idx].IsMark()) markCount++;
            else if (m_ItemLst[idx].IsOpen() == false)
            {
                closeItemLst.Add(m_ItemLst[idx]);
                closeItemCoordLst.Add(new Vector2(x, y - 1));
            }
        }//  下边
        if (x <= m_CurLines - 2 && y >= 1)
        {
            int idx = ConvertCoord2Idx(x + 1, y - 1);
            if (m_ItemLst[idx].IsMark()) markCount++;
            else if (m_ItemLst[idx].IsOpen() == false)
            {
                closeItemLst.Add(m_ItemLst[idx]);
                closeItemCoordLst.Add(new Vector2(x + 1, y - 1));
            }
        }//  右下角
        if (x >= 1)
        {
            int idx = ConvertCoord2Idx(x - 1, y);
            if (m_ItemLst[idx].IsMark()) markCount++;
            else if (m_ItemLst[idx].IsOpen() == false)
            {
                closeItemLst.Add(m_ItemLst[idx]);
                closeItemCoordLst.Add(new Vector2(x - 1, y));
            }
        }//  左边
        if (x <= m_CurLines - 2)
        {
            int idx = ConvertCoord2Idx(x + 1, y);
            if (m_ItemLst[idx].IsMark()) markCount++;
            else if (m_ItemLst[idx].IsOpen() == false)
            {
                closeItemLst.Add(m_ItemLst[idx]);
                closeItemCoordLst.Add(new Vector2(x + 1, y));
            }
        }//  右边
        if (x >= 1 && y <= m_CurRows - 2)
        {
            int idx = ConvertCoord2Idx(x - 1, y + 1);
            if (m_ItemLst[idx].IsMark()) markCount++;
            else if (m_ItemLst[idx].IsOpen() == false)
            {
                closeItemLst.Add(m_ItemLst[idx]);
                closeItemCoordLst.Add(new Vector2(x - 1, y + 1));
            }
        }//  左上角
        if (y <= m_CurRows - 2)
        {
            int idx = ConvertCoord2Idx(x, y + 1);
            if (m_ItemLst[idx].IsMark()) markCount++;
            else if (m_ItemLst[idx].IsOpen() == false)
            {
                closeItemLst.Add(m_ItemLst[idx]);
                closeItemCoordLst.Add(new Vector2(x, y + 1));
            }
        }//  上边
        if (x <= m_CurLines - 2 && y <= m_CurRows - 2)
        {
            int idx = ConvertCoord2Idx(x + 1, y + 1);
            if (m_ItemLst[idx].IsMark()) markCount++;
            else if (m_ItemLst[idx].IsOpen() == false)
            {
                closeItemLst.Add(m_ItemLst[idx]);
                closeItemCoordLst.Add(new Vector2(x + 1, y + 1));
            }
        }//  右上角

        int value = m_MineMap.GetItemValue(x, y);
        if (markCount + closeItemLst.Count <= value) // 剩余未打开的格子总数小于等于数字了，全部标记旗子
        {
            for (int i = 0; i < closeItemLst.Count; i++)
            {
                bool flag = closeItemLst[i].MarkFlag();
                m_GameMainPanel.ModifyLeftMineCount(flag == false);
            }
        }
        else if (markCount >= value) // 标记旗子的格子大于等于数字，剩下的格子全部打开
        {
            for (int i = 0; i < closeItemCoordLst.Count; i++)
            {
                Vector2 coord = closeItemCoordLst[i];
                bool success = OpenItem((int)coord.x, (int)coord.y);
                if (success == false) break;
            }
        }
    }

    // 点击关闭格子时，根据输入方式和操作模式，决定标旗还是标问号，还是打开格子
    void OnItemCloseClick(int x, int y, PointerEventData.InputButton code)
    {
        int idx = ConvertCoord2Idx(x, y);
        if (code == PointerEventData.InputButton.Right || m_CurOperation == EGameOperation.eFlag)
        {
            bool flag = m_ItemLst[idx].MarkFlag();
            m_GameMainPanel.ModifyLeftMineCount(flag == false);
        }
        else if (code == PointerEventData.InputButton.Middle || m_CurOperation == EGameOperation.eTip)
        {
            bool isMark = m_ItemLst[idx].IsMark();
            bool tip = m_ItemLst[idx].MarkTip();
            if (isMark) // 原来被标记旗子的情况下，需要更新剩余雷数
            {
                m_GameMainPanel.ModifyLeftMineCount(true);
            }
        }
        else
        {
            OpenItem(x, y);
        }
    }

    //打开一个关闭的格子
    bool OpenItem(int x, int y)
    {
        if (m_MineMap.IsMine(x, y))//踩到雷
        {
            OnGameLose();
            return false;
        }
        else
        {
            OpenItemRecursively(x, y);

            if (IsWin())
            {
                OnGameWin();
            }
            return true;
        }
    }

    void OnGameWin()
    {
        m_CurStatus = EGameStatus.Win;
        ShowWinPanel();

        m_GameMainPanel.StopPassTimer();// 停止倒计时

        AudioManager.PlaySuccessAudio();
        FxManager.Instance.PlayWinFx();
        RecordManager.Instance.RecordOne(GameMode.Instance.CurMode, (int)m_GameMainPanel.PassTime);
    }

    void OnGameLose()
    {
        m_CurStatus = EGameStatus.Lose;
        ArchiveMgr.Instance.SaveArchive(
                GameMode.Instance.CurMode,
                m_MineMap,
                GetItemLstStatus(),
                m_GameMainPanel.PassTime,
                m_GameMainPanel.LeftMineCount,
                m_GameMainPanel.LeftPullBackCount);
        StartCoroutine(PlayLoseAnim());

        m_GameMainPanel.UpdatePullBack(); // 刷新复活按钮的显示
        m_GameMainPanel.StopPassTimer();// 停止倒计时

        AudioManager.PlayFailureAudio();
        FxManager.Instance.PlayLoseFx();

    }

    void OpenItemRecursively(int x, int y)
    {
        int idx = ConvertCoord2Idx(x, y);
        if (m_ItemLst[idx].IsMark() == true)// 被标记旗子的不打开
        {
            return;
        }
        else if (m_ItemLst[idx].IsOpen() == true)// 打开过的就不用继续展开了
        {
            return;
        }
        else if (m_MineMap.IsMine(x, y) == true) // 是雷的话就不用继续展开了
        {
            return;
        }
        else
        {
            int itemValue = m_MineMap.GetItemValue(x, y);
            if (itemValue > 0)// 如果是数字，只打开自己
            {
                m_ItemLst[idx].ShowMineCount(itemValue);
                // Debug.LogFormat("ShowMineCount:{0}_{1}", x, y);
                return;
            }
        }

        m_ItemLst[idx].Open(); // 空白格打开，然后递归打开周围的格子
        // Debug.LogFormat("Open:{0}_{1}", x, y);

        if (x >= 1 && y >= 1) { OpenItemRecursively(x - 1, y - 1); }//  左下角
        if (y >= 1) { OpenItemRecursively(x, y - 1); }//  下边
        if (x <= m_CurLines - 2 && y >= 1) { OpenItemRecursively(x + 1, y - 1); }//  右下角
        if (x >= 1) { OpenItemRecursively(x - 1, y); }//  左边
        if (x <= m_CurLines - 2) { OpenItemRecursively(x + 1, y); }//  右边
        if (x >= 1 && y <= m_CurRows - 2) { OpenItemRecursively(x - 1, y + 1); }//  左上角
        if (y <= m_CurRows - 2) { OpenItemRecursively(x, y + 1); }//  上边
        if (x <= m_CurLines - 2 && y <= m_CurRows - 2) { OpenItemRecursively(x + 1, y + 1); }//  右上角
    }

    void ShowWinPanel()
    {
        m_WinPanel.Show((int)m_GameMainPanel.PassTime, () =>
        {
            NewGame();
        });
    }

    bool IsWin()
    {
        int unOpenCount = 0;
        for (int i = 0; i < m_ItemLst.Count; i++)
        {
            if (m_ItemLst[i].IsOpen() == false) unOpenCount++;
        }

        return unOpenCount <= GameMode.Instance.MineCount;
    }

    void OpenFirstEmptyItem()
    {
        for (int i = m_CurLines / 2; i < m_CurLines; i++)
        {
            for (int j = m_CurRows / 2; j < m_CurRows; j++)
            {
                if (m_MineMap.GetItemValue(i, j) == 0)
                {
                    OpenItemRecursively(i, j);
                    return;
                }

            }
        }
    }

    IEnumerator PlayLoseAnim()
    {
        for (int i = 0; i < m_CurLines; i++)
        {
            for (int j = 0; j < m_CurRows; j++)
            {
                if (m_MineMap.IsMine(i, j))
                {
                    int idx = ConvertCoord2Idx(i, j);
                    m_ItemLst[idx].ShowMine();
                }
            }
        }
        yield return null;
    }

    int ConvertCoord2Idx(int x, int y)
    {
        return m_CurRows * x + y;
    }

    Vector2 ConvertIdx2Coord(int idx)
    {
        int y = idx % m_CurRows;
        int x = (idx - y) / m_CurRows;
        return new Vector2(x, y);
    }

    int[] GetItemLstStatus()
    {
        int[] statusArr = new int[m_ItemLst.Count];
        for (int i = 0; i < m_ItemLst.Count; i++)
        {
            statusArr[i] = (int)m_ItemLst[i].GetItemStatus();
        }

        return statusArr;
    }

    void _NewGame()
    {
        m_CurStatus = EGameStatus.Start; // 修改游戏状态

        m_MineMap = GetNewMap(); // 换一张新雷图
        for (int i = 0; i < m_ItemLst.Count; i++) // 重置雷区状态
        {
            m_ItemLst[i].Reset();
        }

        m_GameMainPanel.StartPassTimer(null); // 重新显示计时器
        m_GameMainPanel.UpdateLeftMineCount(GameMode.Instance.MineCount); // 重置剩余雷数
        m_GameMainPanel.UpdatePullBack(GameMode.Instance.GetCurPullBackCount()); // 重置退一步次数
        m_GameMainPanel.SelectOperation(EGameOperation.eDig);// 重置雷区操作类型

        OpenFirstEmptyItem(); // 自动点开一片区域
    }

    void HideBreathAnim()
    {
        if (m_TweenBgColor != null)
        {
            m_TweenBgColor.Kill();
            ImgMainArea.color = DigNormal;
            m_TweenBgColor = null;
        }
    }

    void ShowBreathAnim(Color from, Color to, float duration)
    {
        ImgMainArea.color = from;
        m_TweenBgColor = ImgMainArea.DOColor(to, duration);
        m_TweenBgColor.SetEase(Ease.OutCubic);
        m_TweenBgColor.OnComplete(() =>
        {
            ShowBreathAnim(to, from, duration);
        });
    }
    void Update()
    {
        if (Input.GetKeyUp(KeyCode.Space))
        {
            OpenMap();
        }
        if (Input.GetKeyUp(KeyCode.Escape))
        {
            OnNavigationBack();
        }

        // #if UNITY_EDITOR
        //         if (Input.GetMouseButtonDown(0))
        // #else
        //         Touch touch = Input.GetTouch(0);
        //         if (touch.phase == TouchPhase.Ended)
        // #endif
        //         {
        //             AudioManager.Instance.PlayClickSpaceAudio();
        //         }
    }

    void OnNavigationBack()
    {
        if (m_WinPanel.gameObject.activeSelf)
        {
            m_WinPanel.Hide();
            return;
        }

        if (m_ResetConfirmPanel.gameObject.activeSelf)
        {
            m_ResetConfirmPanel.Hide();
            return;
        }

        LeaveGame();
    }

    void OpenMap()
    {
        // for (int i = 0; i < m_CurLines; i++)
        // {
        //     for (int j = 0; j < m_CurRows; j++)
        //     {
        //         if (m_MineMap.IsMine(i, j))
        //         {
        //             m_ItemLst[idx].ShowMine();
        //         }
        //     }
        // }
        m_MineMap = GetNewMap();
        Debug.LogFormat("{0}", m_MineMap.ToString());
    }
}
